home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / db / esm-3.1 / esm-3 / usr / local / sm / src / serverlib / lm / lock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-05  |  6.5 KB  |  260 lines

  1. /*
  2.  *   $RCSfile: lock.c,v $  
  3.  *   $Revision: 1.1.1.1 $  
  4.  *   $Date: 1996/05/04 21:55:51 $      
  5.  */ 
  6. /**********************************************************************
  7. * EXODUS Database Toolkit Software
  8. * Copyright (c) 1991 Computer Sciences Department, University of
  9. *                    Wisconsin -- Madison
  10. * All Rights Reserved.
  11. *
  12. * Permission to use, copy, modify and distribute this software and its
  13. * documentation is hereby granted, provided that both the copyright
  14. * notice and this permission notice appear in all copies of the
  15. * software, derivative works or modified versions, and any portions
  16. * thereof, and that both notices appear in supporting documentation.
  17. *
  18. * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
  19. * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.  
  20. * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  21. * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  22. *
  23. * The EXODUS Project Group requests users of this software to return 
  24. * any improvements or extensions that they make to:
  25. *
  26. *   EXODUS Project Group 
  27. *     c/o David J. DeWitt and Michael J. Carey
  28. *   Computer Sciences Department
  29. *   University of Wisconsin -- Madison
  30. *   Madison, WI 53706
  31. *
  32. *     or exodus@cs.wisc.edu
  33. *
  34. * In addition, the EXODUS Project Group requests that users grant the 
  35. * Computer Sciences Department rights to redistribute these changes.
  36. **********************************************************************/
  37.  
  38. #include "sysdefs.h"
  39. #include "ess.h"
  40. #include "checking.h"
  41. #include "trace.h"
  42. #include "error.h"
  43. #include "list.h"
  44. #include "pool.h"
  45. #include "tid.h"
  46. #include "io.h"
  47. #include "lock.h"
  48. #include "object.h"
  49. #include "msgdefs.h"
  50. #include "thread.h"
  51. #include "semaphore.h"
  52. #include "link.h"
  53. #include "lsn.h"
  54. #include "latch.h"
  55. #include "bf.h"
  56. #include "volume.h"
  57. #include "trans.h"
  58. #include "lm_intfuncs.h"
  59. #include "lm_extfuncs.h"
  60. #include "lm_globals.h"
  61. #include "lock_globals.h"
  62. #include "thread_globals.h"
  63.  
  64.  
  65.  int
  66. lock (
  67.  
  68.     register TRANSREC    *transRec,
  69.     register LOCKID        *lockid,
  70.     register LOCKMODE    *lockMode,  /* IN/OUT */
  71.     FLAGS                flags,
  72.     int                    timeOut,
  73.     int                    weight 
  74. )
  75. {
  76.  
  77.     register LOCKHEADER    *lockHeader;
  78.     register LOCKENTRY    *lockEntry;
  79.     int                    slot;
  80.     LOCKMODE            requestMode = *lockMode;    
  81.  
  82.     TRPRINT(TR_LOCK, TR_LEVEL_1, ("object:%x:%x:%x tid:%x requestMode:%s",
  83.             lockid->lockid.word1, lockid->lockid.word2, lockid->lockid.word3,
  84.             GETTID(transRec), GETMODE(requestMode)));
  85.  
  86.     /*
  87.      *    check to see the state of the transaction
  88.      */
  89.     if ((transRec->transState != T_ACTIVE) && 
  90.         (transRec->transState != T_PREPARED)) {
  91.  
  92.         SM_ERROR(TYPE_USER, esmBADTRANSID);
  93.         return(esmFAILURE);
  94.     }
  95.  
  96.     /*
  97.      *    check the request mode to make sure this is a valid request
  98.      */
  99.     SM_ASSERT(LEVEL_3, (requestMode >= MIN_LOCK_MODE) && (requestMode <= MAX_LOCK_MODE));
  100.  
  101.     /*
  102.      *    get the slot that the lockid will hash to
  103.      */
  104.     slot = hashLockId(lockid);
  105.  
  106.     /*
  107.      *    Get a lock header structure
  108.      */
  109.     if ((lockHeader = findLockHeader(lockid, slot)) == NULL)    {
  110.  
  111.         TRPRINT(TR_LOCK, TR_LEVEL_2, ("object not locked"));
  112.  
  113.         /*
  114.          *    check to see if this is a request for an instant lock
  115.          */
  116.         if (flags & LOCK_INSTANT)    {
  117.  
  118.             return(esmNOERROR);
  119.         }
  120.  
  121.         /*
  122.          *    get a lock header record
  123.          */
  124.         if ((lockHeader = (LOCKHEADER *) poolDeq( &LockHeaderPool )) == NULL)    {
  125.  
  126.             /*
  127.              *    set the error code and return
  128.              */
  129.             SM_ERROR(TYPE_WARNING, esmNOFREELOCKHEADER);
  130.             return(esmFAILURE);
  131.         }
  132.         CHECK_LOCKHEADER_MAGIC(lockHeader);
  133.  
  134.         /*
  135.          *    initialize the lock header fields
  136.          */
  137.         initLockHeader(lockHeader);
  138.  
  139.         /*
  140.          *    get a lock entry record and initialize and queue it
  141.          */
  142.         if ((lockEntry = 
  143.             newLockEntry(transRec, lockHeader, GRANT_LIST,requestMode))==NULL){
  144.  
  145.             /*
  146.              *    return the lock header
  147.              */
  148.             poolEnq( &LockHeaderPool, &(lockHeader->hashList.list) );
  149.  
  150.             /*
  151.              *    return the error code
  152.              */
  153.             return(esmFAILURE);
  154.         }
  155.  
  156.         /*
  157.          *    initialize the fields of the lock header
  158.          */
  159.         lockHeader->hashList.lockid = *lockid;
  160.         lockHeader->modeCount[requestMode] = 1;
  161.         lockHeader->supremum = requestMode;
  162.         listPush( &(LockHashTable[slot]), &(lockHeader->hashList.list) );
  163.  
  164.         /*
  165.          *    initialize the fields of the lock entry
  166.          */
  167.         lockEntry->weight      = weight;
  168.  
  169.         TRPRINT(TR_LOCK, TR_LEVEL_1,
  170.                 ("Thread %d, running for trans %ld, is ALLOCating a %s (flag %d) lock (id %s) entry for trans %d",
  171.                 Active->id, Active->message.header.params.in.tid,
  172.                 GETMODE(lockEntry->lockMode), (int)lockEntry->flags,
  173.                 lockEntry->flags & LOCK_UPGRADE ?
  174.                     printLockId(((LOCKENTRY*)lockEntry->lockHeader)->lockHeader->hashList.lockid) :
  175.                     printLockId(lockEntry->lockHeader->hashList.lockid),
  176.                 lockEntry->headerList.transRec->tid) );
  177.  
  178.  
  179.         /*
  180.          *    update the weight in the transaction record
  181.          */
  182.         transRec->lockWeight += weight;
  183.  
  184.         /*
  185.          *    return success
  186.          */
  187.         CHECK_LOCKHEADER_MAGIC(lockHeader);
  188.         return(esmNOERROR);
  189.     
  190.     } else {
  191.  
  192.         TRPRINT(TR_LOCK, TR_LEVEL_2, ("found lock header"));
  193.  
  194.         CHECK_LOCKHEADER_MAGIC(lockHeader);
  195.  
  196.         /*
  197.          *    put the lock on the top of the queue for better performance
  198.          */
  199.         listMovePush( &(LockHashTable[slot]), &(lockHeader->hashList.list) );
  200.  
  201.         /*
  202.          *    check to see if this transaction holds a lock
  203.          */
  204.         if ((lockEntry = findLockEntry( &(lockHeader->grantedList) , transRec)) != NULL) {
  205.  
  206.             TRPRINT(TR_LOCK, TR_LEVEL_2, ("lock held by transaction"));
  207.  
  208.             /*
  209.              *    check to see if request mode is compatible with
  210.              *    the mode currently held by this transaction
  211.              */
  212.             if (LM_Compat_Upgrade[requestMode][lockEntry->lockMode]) {
  213.  
  214.                 /*
  215.                  *    The lock is compatible so there is no reason to 
  216.                  *    upgrade, so just return the current mode
  217.                  */
  218.                 TRPRINT(TR_LOCK, TR_LEVEL_2, ("lock is compatible"));
  219.                 *lockMode = lockEntry->lockMode;
  220.                 return(esmNOERROR);
  221.             
  222.             } else {
  223.                 
  224.                 /*
  225.                  *    attempt to upgrade the lock
  226.                  */
  227.                 if (upgradeLock(transRec, lockHeader, lockEntry, requestMode, flags) != esmNOERROR) {
  228.                     return(esmFAILURE);
  229.                 } else {
  230.                     /* return the lock mode upgraded to */
  231.                     *lockMode = lockEntry->lockMode;
  232.                 }
  233.             }
  234.  
  235.         } else {
  236.  
  237.             TRPRINT(TR_LOCK, TR_LEVEL_2, ("lock not held by transaction"));
  238.  
  239.             /*
  240.              *    attempt to give the lock
  241.              */
  242.             if ((lockEntry = heldLockEntry(transRec, lockHeader,
  243.                                            requestMode, flags)) == NULL)    {
  244.  
  245.                 return(esmFAILURE);
  246.  
  247.             } else {
  248.  
  249.                 /*
  250.                  *    increment the weights
  251.                  */
  252.                 lockEntry->weight = weight;
  253.                 transRec->lockWeight += weight;
  254.                 return(esmNOERROR);
  255.             }
  256.         }
  257.     }
  258.     return(esmNOERROR);
  259. }
  260.